<?php

/**
 * 处理字符串
 */
//-----------------------------------------------------------

class Handler_string {

    /**
     * 把全角的数字或英文字母转换为半角的
     *
     * @param  string $str ：需要转换的全角字符串
     * @return string  ：完成转换的半角字符串
     */
    public static function str_full_to_half($str) {
        $qj2bj = array(
            '１' => '1', '２' => '2', '３' => '3', '４' => '4', '５' => '5',
            '６' => '6', '７' => '7', '８' => '8', '９' => '9', '０' => '0',
            'ａ' => 'a', 'ｂ' => 'b', 'ｃ' => 'c', 'ｄ' => 'd', 'ｅ' => 'e',
            'ｆ' => 'f', 'ｇ' => 'g', 'ｈ' => 'h', 'ｉ' => 'i', 'ｊ' => 'j',
            'ｋ' => 'k', 'ｌ' => 'l', 'ｍ' => 'm', 'ｎ' => 'n', 'ｏ' => 'o',
            'ｐ' => 'p', 'ｑ' => 'q', 'ｒ' => 'r', 'ｓ' => 's', 'ｔ' => 't',
            'ｕ' => 'u', 'ｖ' => 'v', 'ｗ' => 'w', 'ｘ' => 'x', 'ｙ' => 'y',
            'ｚ' => 'z', 'Ａ' => 'A', 'Ｂ' => 'B', 'Ｃ' => 'C', 'Ｄ' => 'D',
            'Ｅ' => 'E', 'Ｆ' => 'F', 'Ｇ' => 'G', 'Ｈ' => 'H', 'Ｉ' => 'I',
            'Ｊ' => 'J', 'Ｋ' => 'K', 'Ｌ' => 'L', 'Ｍ' => 'M', 'Ｎ' => 'N',
            'Ｏ' => 'O', 'Ｐ' => 'P', 'Ｑ' => 'Q', 'Ｒ' => 'R', 'Ｓ' => 'S',
            'Ｔ' => 'T', 'Ｕ' => 'U', 'Ｖ' => 'V', 'Ｗ' => 'W', 'Ｘ' => 'X',
            'Ｙ' => 'Y', 'Ｚ' => 'Z', '　' => ' '
        );

        return strtr($str, $qj2bj);
    }

    /**
     * 截取UTF8编码字符串从首字节开始指定宽度(非长度), 适用于字符串长度有限的如新闻标题的等宽度截取 
     * 中英文混排情况较理想. 全中文与全英文截取后对比显示宽度差异最大,且截取宽度远大越明显. 
     * @param string $str   UTF-8 encoding 
     * @param int[option] $width 截取宽度 
     * @param string[option] $end 被截取后追加的尾字符 
     * @param float[option] $x3<p> 
     *  3字节（中文）字符相当于希腊字母宽度的系数coefficient（小数） 
     *  中文通常固定用宋体,根据ascii字符字体宽度设定,不同浏览器可能会有不同显示效果</p> 
     * 
     * @return string 	  	
     */
    function u8_title_substr($str, $width = 0, $end = '...', $x3 = 0) {
        global $CFG; // 全局变量保存 x3 的值  
        if ($width <= 0 || $width >= strlen($str)) {
            return $str;
        }
        $arr = str_split($str);
        $len = count($arr);
        $w = 0;
        $width *= 10;

        // 不同字节编码字符宽度系数  
        $x1 = 11;   // ASCII  
        $x2 = 16;
        $x3 = $x3 === 0 ? ( $CFG['cf3'] > 0 ? $CFG['cf3'] * 10 : $x3 = 21 ) : $x3 * 10;
        $x4 = $x3;

        for ($i = 0; $i < $len; $i++) {
            if ($w >= $width) {
                $e = $end;
                break;
            }
            $c = ord($arr[$i]);
            if ($c <= 127) {
                $w += $x1;
            } elseif ($c >= 192 && $c <= 223) { // 2字节头  
                $w += $x2;
                $i += 1;
            } elseif ($c >= 224 && $c <= 239) { // 3字节头  
                $w += $x3;
                $i += 2;
            } elseif ($c >= 240 && $c <= 247) { // 4字节头  
                $w += $x4;
                $i += 3;
            }
        }

        return implode('', array_slice($arr, 0, $i)) . $e;
    }

    /**
     * 'F:8,P:2,Y:A'格式的字符串转换为数组：array("F"=>8,"p"=>2,"Y"=>"A");
     *
     * @param string $a
     * @return array
     */
    public static function strToArray($a) {
        $b = explode(",", $a);
        $c = array();
        foreach ($b as $key => $value) {
            $d = explode(":", $value);
            $c[$d[0]] = $d[1];
        }
        return $c;
    }

    /**
     * 把数组转换为get方式的参数字符串
     */
    public static function arrayToParam($aParam) {
        $sParam = "";
        foreach ($aParam as $key => $value) {
            $sParam.=$key . "=" . $value . "&";
        }
        if (strlen($sParam) > 0) {
            $sParam = substr($sParam, 0, strlen($sParam) - 1);
        }

        return $sParam;
    }

    /**
     * 把xml字符串转换成数组
     *
     * @param unknown_type $xmlStr
     */
    public static function xmlStrToArray($xmlStr) {
        $oResult = simplexml_load_string($xmlStr);
        $str = json_encode($oResult);
        $str = str_replace('O:16:"SimpleXMLElement"', 'a', $str);
        $oResult = json_decode($str, true);
        return $oResult;
    }

    /**
     * 获取字符串当度。支持中英文混合。
     * ASCII中数字、字母和中文等都按实际字数计算。
     * 即一个字母算一个字，一个中文也算一个字。
     * @param $str string 要检测的字符串
     * @return int 字符串包含的字数
     */
    public static function utf8_strlen($str) {
//                $str = htmlspecialchars_decode($str);
        if (empty($str)) {
            return 0;
        }
        $str = trim($str);
        $str = str_replace(array(' ', '&nbsp;', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), array('∵', ' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), $str);
        //获取字符串长度，中文会计算为3个字符。
        $len = strlen($str);
        $mb_len = 0;
        $char = '';
        //循环每个字符
        for ($i = 0; $i < $len; $i++) {
            $char = substr($str, $i, 1);
            //如果当前字符不在基础ASCII码中就认为是中文，与其后的2个字符一起被计算作一个字。
            if (ord($char) > 127) {
                $i = $i + 2;
                $mb_len++;
                continue;
            }
            $mb_len++;
        }
        return $mb_len;
    }

    /**
     * 字符串截取函数，中英文都算一个字
     *
     * @param string $str：原字符串
     * @param int $length:截取字数
     * @param string $endstr:填充字符
     * @return $newstr：返回...
     */
    public static function utf8_substr($str, $length, $endstr = '...') {


        if (self::utf8_strlen($str) > $length) {
//            $str = htmlspecialchars_decode($str);
            $str = str_replace(array(' ', '&nbsp;', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), array('∵', ' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), $str);
            $str = mb_substr($str, 0, $length, 'utf-8') . $endstr;
            $str = str_replace(array('∵', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), array(' ', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), $str);
            return $str;
        } else {
            return $str;
        }
    }

    /**
     * 字符串是不是utf-8编码
     *
     * @param str $string
     * @return bool
     */
    public static function is_utf8($string) {
        return preg_match('%^(?:[\x09\x0A\x0D\x20-\x7E] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} | \xED[\x80-\x9F][\x80-\xBF] | \xF0[\x90-\xBF][\x80-\xBF]{2} | [\xF1-\xF3][\x80-\xBF]{3} | \xF4[\x80-\x8F][\x80-\xBF]{2} )*$%xs', $string);
    }

    /**
     * 把表名和值数组转换为sql语句
     * 
     * param string $tableName 表名
     * param array $aValue :array("a"=>"1","b"=>2,"c"=>"sdfsd")或array(0=>array("a"=>"1","b"=>2,"c"=>"sdfsd"),1=>array(...))
     * return string : 
     */
    public static function createSqlString($tableName, $aValue) {
        $sqlInsert = "insert into $tableName(";

        //插入多条数据
        if (!empty($aValue[0])) {
            $sqlValue = "values";

            foreach ($aValue as $key => $value) {
                if ($key == 0) {
                    $sqlValue.="(";
                } else {
                    $sqlValue.=",(";
                }

                //逗号
                $comma = "";
                foreach ($value as $key1 => $value1) {
                    if ($key == 0) {
                        $sqlInsert.="{$comma}{$key1}";
                    }


                    if (gettype($value1) == "string") {
                        $sqlValue.="{$comma}'{$value1}'";
                    } else {
                        $sqlValue.="{$comma}{$value1}";
                    }

                    $comma = ",";
                }
                $sqlValue.=")";
                if ($key == 0) {
                    $sqlInsert.=") ";
                }
            }
        } else {//插入一条数据
            $sqlValue = "values(";
            //逗号
            $comma = "";
            foreach ($aValue as $key => $value) {
                $sqlInsert.="{$comma}{$key}";

                if (gettype($value) == "string") {
                    $sqlValue.="{$comma}'{$value}'";
                } else {
                    $sqlValue.="{$comma}{$value}";
                }

                $comma = ",";
            }
            $sqlValue.=")";
            $sqlInsert.=") ";
        }

        return $sqlInsert . $sqlValue;
    }

    /**
     * 根据系统配置的密钥，生成校验用的字符串
     * @param <string> $str 需要加密的字符串
     * @param <string> $crypt_key 密钥，默认为系统配置密钥
     * @return <string> 加密后的字符串
     */
    public static function generateCheckCode($str, $crypt_key = "") {
        $str = trim($str);
        $crypt_key = trim($crypt_key);
        $key = empty($crypt_key) ? CRYPT_CODE_KEY : $crypt_key;
        return md5($str . $key);
    }

    /**
     * 根据系统配置的密钥，校验字符串是否给篡改过
     * @param <string> $str 原始字符串
     * @param <string> $str_crypt 加密后的字符串
     * @param <string> $crypt_key 密钥，默认为系统配置密钥
     * @return <bool> 校验一致返回true，否则返回false
     */
    public static function validateCheckCode($str, $str_crypt, $crypt_key = "") {
        $crypt_key = trim($crypt_key);
        $key = empty($crypt_key) ? CRYPT_CODE_KEY : $crypt_key;
        $str_valid = md5(trim($str) . $key);
        $str_crypt = trim($str_crypt);
        return ($str_valid === $str_crypt) ? true : false;
    }

    /**
     * 生成字母与整数混合的随机字符串
     * @param bool $uppercase 是否使用大写字母，默认大写
     * @param int $length 字符串的长度，默认4位
     */
    public static function generateRandCode($uppercase = true, $length = 4) {
        $switch = 0; //标识开关，通过随机决定使用数字还是字母
        $rand_str = '';
        for ($i = 0; $i < $length; $i++) {
            //0时使用字母，1则使用数字
            $switch = rand(0, 1);
            if ($switch == 0) {
                $rand_str .= $uppercase ? chr(rand(65, 90)) : chr(rand(97, 122));
            } else {
                $rand_str .= rand(0, 9);
            }
        }
        return $rand_str;
    }

    /**
     * 将字符串中的中文标点转换成英文标点符号
     * @static
     * @param string $had_cn_symbol_str 含有中文标点符号的字符串
     * @return string 只含有英文标点符号的字符串
     */
    public static function changeCnSymbol2En($had_cn_symbol_str) {
        if (!empty($had_cn_symbol_str)) {
            $cn2en_symbol = array(
                "；" => ";",
                "：" => ":",
                "。" => ".",
                "，" => ",",
                "、" => ",",
                "“" => "\"",
                "”" => "\"",
                "‘" => "'",
                "’" => "'",
                "【" => "[",
                "】" => "]",
            );
            return strtr($had_cn_symbol_str, $cn2en_symbol);
        } else {
            return null;
        }
    }

}

?>